--- title: "19-API 开放平台问题答疑 - API 开放项目项目教程 - 编程导航教程" created: 2025-12-02 tags: - 项目 aliases: - API 开放平台问题答疑 - API 开放项目项目教程 - 编程导航教程 --- # API 开放平台问题答疑 - API 开放项目项目教程 - 编程导航教程 > 请利用好 `Ctrl + F` 来搜索需要的问题 ### 1.前端 #### 1.1 项目对应的版本及所需安装的软件 - nodejs 使用 v16 版本,大于 16.14,可以下载 nvm(Node.js 版本管理工具)来切换多个不同的 Node.js 版本。 - JDK 使用 1.8 版本 - Spring Boot 使用 2.x 版本 - 要下载 git([git 安装教程](https://blog.csdn.net/weixin_47638941/article/details/120632890)) 推荐工具 —— [切换和管理 node 版本的工具](https://github.com/nvm-sh/nvm)。 > **注意:** 如果版本不对,一定会在启动、初始化出现问题🐶 看过来看过来(疯狂挥手.jpg),鱼友一定要更改版本或下载对应软件,再进行项目哦(≧∇≦)ノ #### 1.2 为什么无法移除国际化? 旧版本: ![[fb38687f-d982-4211-a09c-98577863b807-9b7b9e7d.png]]```bash yarn add eslint-config-prettier --dev yarn add eslint-plugin-unicorn --dev ``` ![[cbd179ca-1455-4087-b3c8-c3b3cc6655c5-d54695f1.png]] 注释掉项目目录中的: node\_modules/@umijs/lint/dist/config/eslint/index.js 文件中的`es2022: true`。 旧版本: ![[4dcc86fa-80d3-4288-8f62-2a64ed1d0c4f-9b7b9e7d.png]]```bash yarn add eslint-config-prettier --dev yarn add eslint-plugin-unicorn --dev ``` ![[10f31d48-d279-4bda-a9f9-c78cf59d622f-a7470540.png]] 注释掉项目目录中的: node\_modules/@umijs/lint/dist/config/eslint/index.js 文件中的`es2022: true`。 版本: ![[2e1fbe2a-6813-4fe2-ba70-4baca8acdf18-e6cf73ad.png]]```bash yarn add eslint-config-prettier --dev yarn add eslint-plugin-unicorn --dev ``` ![[b88de82d-ea3b-488d-ba88-266e82f4cc24-a7470540.png]] 注释掉项目目录中的: node\_modules/@umijs/lint/dist/config/eslint/index.js 文件中的`es2022: true`。 ![[1b5fd5c3-d2eb-40c0-bc10-ff4d9fd76d00-6d69aafa.png]] 再次执行`i18n-remove`。 ![[7978923b-1588-45f3-a0c0-667f6f8746b5-a778ddff.png]] 执行成功后,如果 locales 目录还在,手动将其删除即可。 新版本: ![[3b08b597-bca2-4e87-b874-5cec775291ba-e2941bdf.png]] #### 1.3 为什么移除国际化后,菜单栏消失了? 删除国际化后发现菜单栏消失: ![[a2c90914-b54d-4f1d-9cb1-d07f3e7080d7-ac695dbd.png]] 给目录路径:config/route.ts 的路由全加上`name`。 ![[e3bf6954-1798-4e09-b190-b06a0ef03b41-81a0ea88.png]] 给路由加上`name`,如果还是没有,说明加的不够彻底。 ![[273a9e7a-0b99-4075-8244-94ba20ce1ecf-70ed5a30.png]] 再次启动项目,菜单栏显示。 ![[c3c9da29-7c97-4134-a9c5-c6c393aeb5cb-fe96228f.png]] #### 1.4 前端启动出现 ERROR in./src/components/index.md? 根据它提示的路径直接把 index.md、node\_modules、src/.umi 文件夹删除,重新加载依赖包,在终端输入 yarn,再次启动即可 #### 1.5 为什么解决 index.md,运行之后,网页一直转圈? ![[2e92f890-e30c-405b-a994-96f2f7c32422-67e241da.png]] 删除项目 src 里的 .umi 文件,重新启动即可 #### 1.6 为什么前端页面右下角没有"小米饭图标"? 因为项目前端使用的 umi 框架在持续升级,所以现在不太建议使用 umi ui 了,兼容性不好。可以忽略,不影响后续的学习。 **为什么打开前端 umi ui 后,所有的组件都是空白的?** 图片和代码是需要从 github 加载的,可能因为网络原因无法连通 github,可以忽略,不影响后续的学习。 > 这碗"饭"大可不必吃,因为后续项目不会用到,不用纠结╮(╯▽╰)╭ #### 1.7 为什么登录页面没有样式? ![[76ab9d11-2f89-497d-9262-6b0c70f98198-97b05611.png]] 删除 .umi 文件即可。 #### 1.8 使用 pro create myapp 命令,出现‘pro' 不是内部或外部命令,也不是可运行的程序或批处理文件。 nodejs 和 npm 环境没配好,重新检查配置 或在前面加上 npx。 #### 1.9 为什么使用 yarn 命令出现:无法加载文件 C:\Users\13277\AppData\Roaming\npm\yarn.ps1? 是文件权限的问题,需要把 nodejs 的文件权限和项目文件权限全开了,设置成管理员身份运行。 #### 1.10 怎么替换前端样式布局(或界面配置不生效)? 右边蓝色的 ![[640be752-7704-4102-88e3-6a3c8252b3e1-1ebf387e.png]]可以设置样式,调完复制配置。 ![[9806831e-c97f-45e8-9f79-53ec1b95baa9-31f6eb93.png]] 复制配置后,粘贴到 defaultSettings.ts。 ![[9c7a774d-c0a6-41cb-a8dc-1439b885f46f-47ddaa77.png]] 把 app.tsx 的 initialState?.settings 换成 defaultSetting 即可生效。 ![[83a8fe7d-1670-45d2-a6ff-4892135bcb26-b3c9b48e.png]] #### 1.11 怎么更换前端图标? 找到 app.tsx 文件,将 initialState?.settings 换成 defaultSetting。 ![[eae11c6b-7af8-499f-85c3-accd37a5e651-b3c9b48e.png]] 然后找到 defaultSetting.ts,将链接替换成想要的图标链接即可。 ![[280a05c4-15ca-4e6b-9793-171af459a941-1ee30ba2.png]] #### 1.12 为什么初始化文件、命令与回放中不一致? 因为本项目使用的前端框架 Ant Design Pro 在持续更新,如果在按照视频进行操作时遇到错误,请务必参考官方最新文档中的初始化命令。如果仍然存在报错情况,可以尝试以下步骤: - 首先,检查官方文档中的命令和用法,或切换文档版本为和视频一致的。 - 如果仍然遇到报错,可以将错误信息复制并粘贴到百度搜索中进行查询。 - 如果问题依然存在,可以前往框架的 Github Issues 区域搜索相关问题(比如:[Issues · ant-design/ant-design-pro · GitHub](https://github.com/ant-design/ant-design-pro/issues))。大多数情况下,你遇到的问题已被其他开发者提出,并且可能已经有了解决方案。 运用以上方法,希望鱼友可以更灵活地解决遇到的问题。请记住,任何教程都有保质期,通过学会阅读官方文档和积极自主解决问题,才能在编程学习中突破难,使学习旅程不受任何困扰ヾ(´・ω・`)ノ #### 1.13 为什么登录状态失效了? 登录后,刷新页面,又要重新登录,说明前端没有 cookie,登录状态失效。 在 requestConfig.ts 中添加上`withCredentials: true`. ![[89a0f271-0ed9-4c2e-ae10-d7726704a251-f8501012.png]] 再次登录,刷新页面,没有跳转回登录页面,成功。 ![[482abb5b-9dd2-4066-bd23-887a20cc2ad7-9901330a.png]] #### 1.14 为什么头像一直在加载? 现右上角的头像一直加载,这里使用编程导航头像,将链接粘贴至后端数据库中。 ![[b4664c74-8114-42e4-bd57-6564ff791619-e06f59f0.png]]```bash ``` 用户名设置为:老鱼皮。 ![[7513edfd-d897-44c9-860e-ab14c52040ac-26399ad5.png]] 在 AvatarDropdown.tsx 按[Ctrl+F]。 ![[0028bb56-f0f2-48fe-a0e0-b923e2b3b17a-ca4cc2c5.png]] 把所有的 currentUser 换成 loginUser,name 换成 userName。 ![[c1607408-779b-4f9e-99e2-ca2935e876ce-8a592e90.png]] #### 1.15 怎么实现前端注销登录? 找到`AvatarDropdown.tsx`,把默认的注销方法(loginOut)改成我们后端自己的方法(userLogoutUsingPOST)。 ![[1c2ab3ba-cf79-4327-8891-622630dbd801-25a2131e.png]] 在 userLogoutUsingPOST 后编写跳转回登录页面。 ![[f5c62c02-797d-491b-ac5f-183b72182e67-ea781bdc.png]] 把原先的 loginOut 删掉。 ![[6114ba66-ea69-40b2-a116-61a4dd44a4bd-69eecbef.png]] 登录之后,点击退出登录测试即可。 ![[fe2a6c3b-0c4b-470e-9222-494a2c7eac27-a1a1580c.png]]) #### 1.16 为什么点击修改按钮,提交后提示操作失败,id 没有传递给后端? ![[b19f6aad-5d59-4f0e-9702-3bfa409c398a-d43132f5.png]] 把类型换成自己的。 ![[cb2b9363-5791-4614-8254-acd3a4cec2e4-270a5a12.png]] 修改`更新节点`即可。 ![[28a0aee6-711f-4a8f-88e5-abe79dbc5dc0-30857203.png]] #### 1.17 为什么前端发布或下线按钮重复多次显示? 两种方法: 1. 设置不同的 key 通过给发布按钮和下线按钮设置不同的 key 值来解决按钮重复渲染。 ![[9ce1960d-a09a-4ad8-bf72-5ae266ce76b7-c8cc9a28.png]] 1. 修改条件渲染逻辑 代码中是通过条件来渲染按钮,重新修正代码: - 首先判断状态是否为 0,如果是 0,则渲染发布按钮; - 如果状态为 1,则渲染下线按钮;其他状态的情况下,不进行任何渲染。 ![[10cb45fd-3298-4558-b644-e614c30bd40c-1b873793.png]] #### 1.18 为什么使用 npm run start 命令(或登录),报 404? 注释`/config/proxy.ts`中的`dev:{}`。 #### 1.19 为什么前端初始化出现:Directory import'D:Yis notsupported resolving ES modules imported from D:# #front\code\apilapi-front\node\_modules\real-require\src\index.js? 为避免造成问题,目录不要出现空格、#、特殊符号、中文等。 #### 1.20 为什么登录请求路径一直有个前缀的 localhost:8000? 在前端项目中设置的,先全局搜索有没有 localhost:8000,可以去对比下官方代码,request.ts 文件。 #### 1.21 为什么前端必须进行两次登录,才能进入到登录后的页面? 找到这里。 ![[0e9acf33-19b0-453b-b953-63dcc13d5fb3-cf1d1a08.png]]```tsx const handleSubmit = async (values: API.UserLoginRequest) => { try { // 登录 const res = await userLoginUsingPOST({ ...values, }); // 如果登录成功(响应有数据) if (res.data) { // 获取当前URL的查询参数 const urlParams = new URL(window.location.href).searchParams; // 设置一个延迟100毫秒的定时器 // 定时器触发后,导航到重定向URL,如果没有重定向URL,则导航到根路径 setTimeout(() => { history.push(urlParams.get('redirect') || '/'); }, 100); // 更新全局状态,设置登录用户的信息 setInitialState({ loginUser: res.data }); ```javascript return; } // 如果抛出异常 } catch (error) { // 定义默认的登录失败消息 const defaultLoginFailureMessage = '登录失败,请重试!'; // 在控制台打印出错误 console.log(error); // 使用 message 组件显示错误信息 message.error(defaultLoginFailureMessage); } ``` }; ```bash #### 1.22 直接拉取鱼总前端代码,为什么运行之后报错:Module not found: Error: Can't resolve '@ant-design/cssinjs'? ```bash npm install @ant-design/cssinjs --save ``` #### 1.23 为什么新建模态框的名字和回放的不一样? 前端版本升级,换了一个命名。 #### 1.24 为什么删除国际化时,遇到报错:Plugin"react"was conflicted between".eslintrc.js"and"BaseConfig插件“之间发生冲突? 重建一个项目,先不要 install 依赖,先执行 i18n-remove,,再去npm install(或者yarn),便不会报错。 #### 1.25 为什么注释了 es2022:true,删除国际化还是报错? ```text nvm list available nvm install 18.16.0 nvm use 18.16.0 ``` #### 1.26 退出登录怎么写? 找到 AvatarDropdown.tsx。 ![[be00d6eb-9586-4167-aed6-0c25aa1fe0d1-bb603b73.png]] 把默认的注销方法(loginOut)改成我们后端自己的方法(userLogoutUsingPOST)。 ![[0e208495-af3f-409c-a957-d69d1a4a8651-d835d74c.png]] 在 userLogoutUsingPOST 后编写跳转回登录页面。 ![[403c161b-8fdf-4269-856d-92f8da6f7f11-3421f502.png]] 这样用户点击`退出登录`后,会先执行登出操作,并清除全局状态中的用户信息,然后跳转到登录页面。 把原先的 loginOut 删掉。 ![[cf2d58a4-06ae-4518-8fdc-c95804a8b7dc-69eecbef.png]] ```javascript import { userLogoutUsingPOST } from '@/services/yuapi-backend/userController'; import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons'; import { useEmotionCss } from '@ant-design/use-emotion-css'; import { history, useModel } from '@umijs/max'; import { Spin } from 'antd'; import type { MenuInfo } from 'rc-menu/lib/interface'; import React, { useCallback } from 'react'; import { flushSync } from 'react-dom'; import HeaderDropdown from '../HeaderDropdown'; export type GlobalHeaderRightProps = { menu?: boolean; children?: React.ReactNode; }; export const AvatarName = () => { const { initialState } = useModel('@@initialState'); const { loginUser } = initialState || {}; return {loginUser?.userName}; }; export const AvatarDropdown: React.FC = ({ menu, children }) => { const actionClassName = useEmotionCss(({ token }) => { return { display: 'flex', height: '48px', marginLeft: 'auto', overflow: 'hidden', alignItems: 'center', padding: '0 8px', cursor: 'pointer', borderRadius: token.borderRadius, '&:hover': { backgroundColor: token.colorBgTextHover, }, }; }); const { initialState, setInitialState } = useModel('@@initialState'); const onMenuClick = useCallback( (event: MenuInfo) => { const { key } = event; if (key === 'logout') { flushSync(() => { setInitialState((s) => ({ ...s, loginUser: undefined })); }); userLogoutUsingPOST(); const { search, pathname } = window.location; const redirect = pathname + search; history.replace('/user/login', { redirect }); return; } history.push(`/account/${key}`); }, [setInitialState], ); const loading = ( ); if (!initialState) { return loading; } const { loginUser } = initialState; if (!loginUser || !loginUser.userName) { return loading; } const menuItems = [ ...(menu ? [ { key: 'center', icon: , label: '个人中心', }, { key: 'settings', icon: , label: '个人设置', }, { type: 'divider' as const, }, ] : []), { key: 'logout', icon: , label: '退出登录', }, ]; return ( {children} ); }; ``` 测试一下,前端在终端输入`yarn run dev`,访问 ,登录。 ![[54050fee-02a9-47f7-b878-8025c39653d1-a1a1580c.png]] 登录之后点击头像→`退出登录`,退出成功,跳转回登录页。 ![[df7c3a68-5e3f-4a2e-88dc-6add7aecd972-17d6574e.png]] #### 1.27 为什么点击新建或修改控制台报错:Encountered two children with the same key? key 重复,将其中一个 key 进行修改。 ![[2d2ef47a-d640-4b36-85f9-515ad3366ac8-e7dc916f.png]] #### 1.28 为什么进入接口管理页控制台报错:`visible` is deprecated which will be removed in next major version,please use `open` instead? ![[2ad01e0d-83df-4672-bb60-ee544b0db3a2-884d73c6.png]] 将这些组件的 visible 属性改为 open 属性。 src/pages/InterfaceInfo/index.tsx: ![[fc123584-1101-4887-991b-64117178df48-8b26ddd9.png]] src/pages/InterfaceInfo/components/CreateModal.tsx: ![[ab3f2902-19ba-42a3-a7c0-0c27640513af-973314de.png]] src/pages/InterfaceInfo/components/UpdateModal.tsx: ![[d1447d9d-3921-4de5-af09-6d0847d4954b-322b9d33.png]] #### 1.29 为什么控制台报错:Each child in a list should have a unique "key" prop? ![[17e15451-a34e-48df-a530-cc82abee92a3-8826cfd8.png]] 修改 src/pages/InterfaceInfo/index.tsx 中 ProTable 组件的 rowKey="id": ![[fcb502eb-b546-4911-ae1b-45ced9029ad9-79766dea.png]] #### 1.30 为什么使用 openapi 生成 services 文件报错:Cannot read properties of undefined(reading 'filter')? 删掉 operationObject.parameters = operationObject.parameters.filter((item) => { var \_a; return ((\_a = item) === null || \_a === void 0 ? void 0 : \_a.in) !== 'header'; }); 解决参考: #### 1.31 为什么使用 pro create yuapi-frontend 报错:Error:Command failed with exit code 128:git clone GitHub-ant-designant-design-proUseAntDesignlikeaPr.…--depth=1 yuapi-frontend? 如果排除不是软件没安装或者是版本问题: 1. 是否安装了 git 2. 是否安装了 yarn 3. nodejs 的版本要 16 的,大于16.14 4. 文件夹是否有管理员权限 5. 如果不行,就用 npm/yarn(换一个包管理器)来安装 pro-cli,如果安装后还是无法执行 pro 命令,可能是系统没有给安装成功 pro 工具的目录配置环境变量。如果是用 npm 安装的,可以重新在 node.js 官网安装node(自动重装npm),再安装 pro 试试。 6. github 不能访问,如果 github 不能访问先解决 github 的问题。博客参考: #### 1.32 登录之后把用户信息存到 session 中,然后再次发出请求从 session 获取用户信息,为什么第二次从 session 中获取到的值为空? 在 app.tsx 中的 request 函数加上 credentials:'include'。 #### 1.33 执行 pro create yuapi-frontend 报错:C:\Users\YY\AppData\Roaming\npm\node\_modules@ant-design\pro-cli\src\create\generators\ant-design-pro\index.js:10 const sortPackage = require('sort-package-json');? 执行 npm install sort-package-json@1.57.0 -O。 #### 1.34 怎么解决表格内容过长? ![[b2f8b1ce-cf70-45d1-9bd9-c9cf18945293-989ab278.png]] ![[4964cd69-fbd6-4a8f-bb5c-03e36f2e8997-dd85ab0f.png]] 解决参考: #### 1.35 为什么前端安装依赖失败? 可以尝试更换一个包管理器,比如 yarn(或 npm、pnpm)。 #### 1.36 为什么直接拉取前端代码登录后,会重新回到登录页? app.ts 里配置的是 localhost,如果用 127.0.0.1 来访问,cookie 就种不上,改成 127.0.0.1 即可。 ### 2.后端 #### 2.1 为什么后端初始化启动显示 java:错误:无效的源发行版:17? 首先点击锤子旁边的矩形的倒三角,会出现一个下拉框,点击 Edit Configurations。 ![[e25b4301-f3b6-42f0-863f-7d16a5ef0fde-a12782c2.png]] 把 Build and run 下面的改成 java 8(注意不是 18)。 ![[a2f988ce-2154-42fe-8491-6b158313f29b-2328d79a.png]] 点击 File -> settings ->图片中的选项,将 Target bytecode version 改成 8,project bytecode version 改成 8。 ![[122586da-864f-4ac0-885c-8605ff30631a-e5d63032.png]] 点击 File -> project Structrue 将project,modules 改成 java 8 ![[e1202644-0cf5-4e1d-a9ab-99b89e1bbf41-77d135e1.png]] 将上述地方改成相同 JDK。 如果还是显示无效的源发行版:18,只能说明 Maven 上的依赖不对(在pom文件里),再调一个依赖,一定记得要刷新 maven,不然改了之后没用。 ![[a2567b40-bef6-4449-84f4-29db76248a8e-741b785a.png]] 请参考这篇文档:[文档](https://blog.csdn.net/tumu6889/article/details/130307386?ops_request_misc=&request_id=&biz_id=102&utm_term=java:%20%E9%94%99%E8%AF%AF:%20%E6%97%A0%E6%95%88%E7%9A%84%E6%BA%90%E5%8F%91%E8%A1%8C%E7%89%88%EF%BC%9A17&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-130307386.nonecase&spm=1018.2226.3001.4187) #### 2.2 为什么 idea 右侧 maven 菜单消失? - help - 或者右键 pom.xml 然后 add as maven project #### 2.3 为什么 yuapi-client-sdk 项目导入没有问题,但爆红了? 1)把报错的文件拖到其他包里,然后拖回原来的位置。 2)在对应项目路径下执行`mvn idea:module` #### 2.4 关于项目 Nacos 依赖及安装推荐版本 Nacos 下载 2.1.1。 ```text https://github.com/alibaba/nacos/releases/download/2.1.1/nacos-server-2.1.1.zip ``` yuapi-backend、yuapi-gateway 项目的依赖设置为: ```xml org.apache.dubbo dubbo 3.0.9 com.alibaba.nacos nacos-client 2.1.0 ``` 用 macOS M1 的鱼友们使用 1.4.2 版本。 ```text https://github.com/alibaba/nacos/releases/download/1.4.2/nacos-server-1.4.2.zip ``` 相关博客:[macbook pro m1 芯片,2021版本安装nacos报错踩坑](https://blog.csdn.net/asd991543753/article/details/127615419)。 ![[d693e7da-ebf0-4205-9880-edf3a0676eba-92c96756.png]] macOS M1 的 yuapi-backend、yuapi-gateway 项目的依赖设置为: ![[104f4fa7-03f3-4fbe-a9a4-9290ac93e113-3f1d928e.png]] ![[fd4a080b-84a7-45b2-a2a0-53e56f25dc04-9b578f65.png]] #### 2.5 怎么将 sdk 和 interface 放到 yuapi-backend 目录下? 放到同一个目录下,在上级目录使用 idea 打开即可。 #### 2.6 拉取了鱼总的后端代码,显示缺少 yuapi-client-sdk、 yuapi-common 这个包,这个依赖包要怎么下载(或 java 怎么下载依赖包)? 来到 yuapi-client-sdk 包中,对已经写好的依赖包进行打包,点击右侧菜单栏中的 maven。 ![[4703147b-6fd7-4d30-99d0-b6f3e849b609-3b659bf2.png]] 点击 Lifecycle → install,把它安装为本地的依赖。 ![[29f5816c-6cf8-4857-bf37-3572af190f46-8f13df34.png]] **或** 在后端终端中进入 yuapi-client-sdk 目录中,执行`mvn install`命令。 yuapi-common 同理。 #### 2.7 为什么在 idea 使用 yarn 命令显示:The term 'yarn' is not recognized as the nane of a cmdlet, function, script file, or operable program? ![[4f7f030c-ee5d-4bf6-8ed5-8bf8ab687f0c-56c37da1.png]] #### 2.8 mac 整项目,为什么用 nacos 2.2.1 版本可以启动,能注册 provider,但 gateway 一启动就报错? 可能是 nacos 放在本地时,consumer 调用 provider 方法时会超时,可以在云服务器上整了个 nacos,把本地的 provider 和 consumer 都注册到云端的 nacos 上。 #### 2.9 nacos 能启动生产者,不能启动消费者? 1. 检查有没有注册成功,地址就是 localhost:8848/nacos 2. 检查统一路径,鱼总的路径是 com.yupi.project.provider,检查一下消费端和服务端是否一致 #### 2.10 nacos 以单机模式启动了,为什么项目启动不了? 1. 可能是没有添加 nacos 注册依赖 dubbo-registry-nacos。 2. 本地 nacos 版本要跟 maven 的一样,最好是 2.1.1。 #### 2.11 导入 hutool 依赖,写完客户端,为什么向服务端 controller 发送请求报错:Connection refused:connect(或 hutool 连接失败)? 1. 检查请求 url 2. 所有项目是否全部启动,可能忘记开服务端,用户端启动请求找不到 #### 2.12 怎么解决用 hutool 调用模拟接口,中文编码异常的问题? 两种方法: 1. 将参数编解码的方式。 ![[b048980a-2e5f-4d82-a216-5629ea17a01d-11aa37c0.png]] ![[aafa52b9-886e-4e11-bea4-ab77569856f1-be8804c3.png]] 1. 修改接收请求那一端的编码(见 29 行) ![[9ed56665-e1fa-480f-9ec9-c2554bca4268-35635045.png]] #### 2.14 第三期最后调用接口时,userRequestParams 用 Gson 转为 User,为什么得到的值是null? ![[281ef236-258b-406c-81cd-9dcde8d636e9-5d71500d.png]] 1. 属性名不一致,把 name 改为 username。 2. 或因为生产者消费者在同一机器上会产生的警告。参考 Github 上的项目讨论区: #### 2.15 启动报错:Caused by:javax.management.InstanceAlreadyExistsException:org.springframework.boot:type=Admin,name=SpringApplication? 可能启动类多写了一个实例。 #### 2.16 为什么客户端调用接口出现:Error request,response status:403?而弹框显示"请求成功"? 1. 可能在 gateway 项目里根据 accessKey 拿到调用者的时候,给 accessKey 加了个引号,传进去的就是 "accessKey" 而不是 accessKey。 2. yuapi-gateway 项目是否启动 #### 2.17 为什么无法更新接口信息,报错:Cause: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual thatcorresponds to your MySQL server version for the right syntax to use near 'WHERE id=4 AND isDelete=0' at line1? 可能只传了 id,不是 IdRequest。 #### 2.18 后端模板在哪里下载?下哪一个? 下载地址: 选择老版本下载。 ![[25d140e7-b7ff-4ae9-9ade-de795e2a04d4-077b7e8b.png]] #### 2.19 为什么 maven install 时报错:无效的标记:--release? 把 springboot 的版本号改低。 #### 2.20 为什么在 interface 项目的测试类中运行 contextLoads() 方法报错:Error creating bean with name'com.evan.evanapiinterface.EvanapiInterfaceApplication Tests': Injection of resourcedependencies failed ...? 可能是 springboot 和 jdk 版本太高,springboot 改成 2.x 版本,jdk 改成 1.8 版本。 #### 2.21 为什么完成后端的增删改查后,找到不到 mapper 的 xml 文件? 如果在完成的后端删改查中,前端发送请求但是找不到实体类的字段,这可能是由于以下几个原因导致的: 1. Mapper XML 文件命名不正确:请确保 Mapper XML 文件的命名与实体类对应的 Mapper 接口名一致,并且文件后缀为 .xml。如果 Mapper XML 文件的命名不正确,将会导致找不到实体类的字段。 2. Mapper XML 文件中配置不正确:在 Mapper XML 文件中,需要正确配置实体类以及相应的字段映射关系。请检查 Mapper XML 文件中的配置是否正确,并且与实体类中的字段保持一致。 3. 数据库字段与实体类字段不一致:如果数据库字段与实体类字段不一致,可能会导致找不到实体类的字段。在这种情况下,你需要根据实际情况进行配置,确保数据库字段与实体类字段能够正确映射。 检查以上几个方面,逐一排查问题所在,并确保前端发送请求时能够正确找到实体类的字段。 #### 2.22 为什么修改完后端增删改查后,接口文档看不到增删改查的接口? 没扫描到 controller 代码,改了包名,需要把 mapper 下也改成自己文件名称。 #### 2.23 为什么加入网关后,无法调用接口了? 访问路径出错,NameController 类的地址经过多次修改,很有可能因为不想修改而被忽略。 #### 2.24 为什么网关调用方法获取的 invokeUser 为空? 因为 accessKey 有两条一样的,selectOne 查出两条报错了。 #### 2.25 为什么 yuapi-client-sdk、 yuapi-common 总是报错,删除再 install 后缀都是 lastUpdated? 先 mvn clean 一下,然后 mvn install 打本地 jar 包,确认引入的版本号和打包的一致。 #### 2.26 使用 maven 安装依赖时测试报错,发现是数据库连接有问题,为什么会出现问题? 1.检查本地装的 mysql 是多少版本,还有 maven 导入依赖是什么版本 2.密码最好不要以 0 开头 #### 2.27 为什么 redis 启动了,项目运行报错:Unable to connct to Redis server: localhost/127.0.0.1:6379? redis 配置有问题, 可能是你给 redis 设置了密码。 #### 2.28 dubbo rpc 调用到返回值拿不到,报错:Failed to find any request match the response,response id:80、Failed to invoke the method getUserInterfaceInfo in the service.InnerUserInterfaceInfoService...? 可能是 dubbo 调用超时,把超时时间设置长一点。 #### 2.29 配置完注解报错:Failed to configure a DataSource:'url' attribute is not specified and no embedded datasource could be configured? 数据库驱动有问题,如果不用数据库驱动,就直接在配置文件注释掉。 #### 2.30 为什么 debug 到 ak 时,和自己设置的 ak 不一样? accesskey 是哪个账号的,就登录那个账号。 #### 2.31 使用新版 SpringCloud Gateway + Nacos 搞负载均衡,为什么报错 503,并且控制台没有异常打印? 要手动引入 spring-cloud-starter-loadbalancer 的 Jar 包,因为新版没有集成 Ribbon 没法搞负载。不然会报错 503,而且控制台没有异常打印。 #### 2.32 项目的 mysql 必须是 8.0+ 的版本吗? 可以装一个 5.7+ 的试一试,应该也是 ok 的。 #### 2.33 为什么后端生成的 sql 语句强制添加了一条 age 的条件? POJO 最好用包装类而不是 int,会被默认赋值。 #### 2.34 为什么 mysql 数据库连接时区不对? 使用`jdbc:mysql://[localhost:3306/test?serverTimezone=GMT](http://localhost:3306/test?serverTimezone=GMT)`设置 url 时区。 ![[cbbb9a1e-032b-45d4-92e0-0ea7180c681a-858b8bbd.png]] #### 2.35 为什么在接口文档注册用户,返回系统错误? ![[06126796-6a3f-4263-be70-90c7177e37bc-56ff512e.png]] 可能是 yml 的 mysql 密码有误。 ![[43975922-dff3-4267-9d2d-baf2e3fed417-a5782b81.png]] #### 2.36 为什么网关项目启动失败? 1. 注意 Nacos 服务是否启动、服务是否注册成功,如果失败的话要确认 Nacos、Dubbo 版本号是否和鱼皮的一致。 2. 注意端口号是否被占用,端口被占用可以杀死进程或换个端口号。 #### 2.37 接口测试调用获取用户名,传入值后,为什么在请求后接收为空? 在实际被调用的接口处打断点,查看接收到的对象和字段是什么,另外一定要注意字段名称大小写的一致性。(Spring MVC 会自动转换大小写)。 #### 2.38 为什么启动nacos 出现 BindException: Address already in use: bind? 1. 端口杀掉,把两个项目分别指定不同的端口号,重启 idea 2. 这样修改 qos 端口 ![[7b138af1-6fff-438d-883c-6fef6bfe8460-9454e9f4.png]] ### 3.部署&上线 #### 3.1 为什么上线后,前端有些页面显示 404(或动态路由 404)? 1. 没有配置 nginx 代理路径,默认前端应该是 history 模式,需要服务端支持,否则因为找不到 html 文件只能访问主页。 2. 或者把 a 标签换成了 Link,注意大写 L,还有 href 换成了 to,以及 import Link 3. 或者在 nginx 配置文件里面加上`try_files $uri $uri/ /index.html;` 解决参考: #### 3.2 为什么使用 docker 容器通过 dockerfile 文件对项目打包成镜像显示无法找到关于 client-sdk、common 的 jar 包? 1.是否配置 nginx 代理路径,默认前端应该是 history 模式,需要服务端支持,否则因为找不到 html 文件只能访问主页 2.检查接口路径是否正确 3.检查 api 服务是否启动成功 #### 3.3 为什么部署后,nacos 在项目中连接不上,显示 Client not connected,current status:STRING? 1. 将 nacos 版本改为 2.1.1,nacos 依赖版本和 nacos 一致。 #### 3.4 为什么使用 sh startup.sh -m standalone 命令,nacos 一直启动不了(或连接不上)? 1. 内存不足,可以加钱升 4G,或者修改 nacos 最大最小内存。 2. nacos 需要两个端口:8848、9848(或 9848、9849、3306、8090、8123、8101),因为 nacos 2.0 版本新增了 grpc 通信。(还是报 grpc 连接不上,把以上 7 个端口全开了) ![[05a072a3-d3a6-4735-b241-37cab4b4cd36-3a78db00.png]] 1. nacos 需要配置一个数据库 #### 3.5 为什么项目上线调用接口出现:Error request,response status:403? 1. 检查拦截内网 2. 检查数据库 3. 检查是否给接口调用次数 #### 3.6 部署上线成功,为什么每隔几天进行在线访问就会一直转圈访问不了? 可能是网速的原因。 #### 3.7 打包项目上传到服务器,为什么每个项目执行 jar 包报错:"Unable to read meta-data forclass com.yupi.openAPIClientsdk.OpenAPIClientConfig"? 看看是不是上传 jar 包后占用 0 内存,试着在 xml 里添加 springboot 的父级依赖。 #### 3.8 为什么 nacos 没连接一会就挂了? 2核 2G 内存不够,容易挂。 1. 升到 4G 以上。 2. 把 nacos 内存调小。 #### 3.9 为什么在云服务器上部署项目时,Dubbo 模块启动失败,无法注册 dubbo(或 nacos)? 1. 注意 Nacos、Dubbo 的版本,注意 Nacos 地址的配置填写。 2. 将 Nacos 链接地址改为公网 IP 能访问到的地址。 #### 3.10 项目上线,为什么报错 403? 注释网关里的黑白名单。 #### 3.11 为什么使用云服务器的 nacos 会报错? 1. docker pull 的镜像要指定 nacos 版本,最好和本地一致。 2. 查看 nacos 运行日志,查看 nacos 的地址,在后端配置地址配置 nacos 运行的地址。注意,nacos 每次重启后地址可能会改变,所以谨慎重启 nacos,这个随机地址的问题可以后续再去解决。 #### 3.12 项目上线遇到跨域问题,怎么解决? 可以查看用户中心项目最后两期回放学习部署上线操作,里面有提到几种解决跨域的方式。 #### 3.13 运行 jar 包报错:Invalid initial heap size: -Xms256M /www/wwwroot/api-backend-master/api-backend-0.0.1-SNAPSHOT.jarError: Could not create the Java Virtual Machine.Error: A fatal exception has occurred. Program will exit? ```text /usr/bin/java -Xmx1024M -Xms256M -jar /www/wwwroot/api-backend-master/api-backend-0.0.1-SNAPSHOT.jar --server.port=7529 --spring.profiles.active=prod ``` 2.把 JAVA 前面的路径去掉,然后去掉 jvm 的配置信息 #### 3.14 nacos 用 docker 部署,为什么 ip 地址无法访问? nacos 地址会变成 docker 网卡的地址,导致 ip 地址无法访问。 解决参考: #### 3.15 如何正确设置 cookie 的 domain,使其在访问域名和 IP 时工作正常? 需要理解 cookie 作用域和 session 机制。cookie 必须种在和后端请求域名、以及前端域名保持一致的域名(或者子域名)下,才会在发送请求时自动带上 cookie、并且不会出现 cookie 跨站问题。 具体的解决方案: 1)建议前端和后端接口域名保持一致,用 Nginx 进行端口转发。 2)修改 application.yml 中 cookie.domain 配置,指定种的 cookie 域名为前端域名、后端请求的公共子域名。 #### 3.16 在部署 API 项目时,使用 nginx 反向代理,后端项目配置出现"unbind dubbo module"情况? 可以先能够使用外网 IP 访问到 Nacos,然后所有用到 Nacos 的服务中,把地址改为能访问到 Nacos 的外网 IP 地址。(当然也可以用内网 IP 地址)。 #### 3.17 部署时怎么配置 dubbo? 跟本地部署一样的,在服务器上安装 **特定版本** 的 Nacos,用到 Dubbo 的项目中配置线上可访问的 Nacos 地址。 ### 4.提问 #### 4.1 鱼总的 sdk 是直接调用对应方法,如果接口变多,那不是每多一个接口就要去 sdk 修改代码,这样就不太符合开闭原则? 直播的时候说过,不是不符合开闭原则,本身接入的新接口参数什么的就是不固定的,为了最方便的给开发者使用,就需要审核并且提供对应的 sdk,可以去看腾讯云的 sdk ,也是在不断更新。觉得麻烦可以写个工具根据接口生成调用代码,自动更新。 #### 4.2 怎么开发一个不需要任何参数的接口? getheadmap 方法再弄一个不需要参数的即可。 #### 4.3 如果每添加一个 api 接口,都需要一个对应的 sdk 和模拟接口是吗? sdk 本身就是要更新和维护的,因为要保证接口的质量,但是你可以根据接口来生成 sdk 代码。 #### 4.4 在 interface 模块中,每增加一个接口,都要在 client sdk 中增加对应的方法,真实企业的设计也是这样的吗? 直播有讲,本来就是要人工开发 sdk 的,想图省事儿可以开发个自动生成 sdk 代码的工具。 #### 4.5 准备用宝塔部署 API 项目,能不能按照用户中心部署上线的思路来整?需要单独部署 api-gateway 和 api-interface 项目吗? 前后端部署其实和用户中心一样的,ant design pro 官网也有部署部分的说明,比较复杂的是 nacos 部署,要注意使用的版本,建议先在本地跑通,还要注意要保证几个后端服务之间的连通性(最好先部署到同一个服务器上)。 需要单独部署 api-gateway 和 api-interface 项目。 #### 4.6 前端的 created 函数不能拿到 data 的值吗? ![[95e75697-4088-4bf2-b202-4fd3374ff1b6-76cf3452.png]] searchObj 应该使用 this.searchObj,searchObj 也是 data 里定义的对象,传参的时候也要写 this 指定这个 vm 实例。 #### 4.8 把鱼总的前端代码直接拉取下来要改哪些地方? 一、需要先安装好相关软件,可见标题: **1.1 项目对应的版本及所需安装的软件** 二、运行前端代码,根据报错信息解决问题,报错可见本文档问题答疑查找,或者参考其他鱼友的笔记 #### 4.9 鱼总说密钥不能直接放到请求头中,很容易被截取到,可以被用来访问服务器端,那我在客户端就算加密了,加密的字符串拿到之后依然可以去访问服务器端,请问加密有起到作用吗? 1.利用 nonce+timestamp 可以防止重放,后端可以通过较验这两个参数保证一个请求只能使用一次,这样拿到你这个字符串也没什么意义。 2.通过身份验证来限制访问 API。可以将每个 API 用户分配一个唯一的身份标识符,并且要求每个 API 请求都在请求头中包含它们的身份标识符。服务器可以验证这个标识符是否属于合法用户,并根据用户权限决定是否接受请求。 3.基于密钥的身份验证。在这种情况下,每个 API 用户都有一个唯一的密钥,它被用来在请求头中验证用户身份。服务器端在接收到请求后,会根据密钥确定用户身份,并根据用户权限决定是否接受请求。 #### 4.10 想上线项目,服务器的配置要买多少? 2核 4G 即可,2核 2G 勉勉强强,就是会很卡,nacos 比较吃内存,也有可能吃内存太大导致启动失败。 #### 4.12 网关鉴权的实现中,globalfilter 是从请求头中拿到 sign 后,再根据调用者信息生成serverSign 去比对,但是,请求不应该先进入网关再发送请求吗? 网关只负责所有的接口,不包括 backend 项目,在线调用时前端请求直接到 backend,由 backend 再发送请求到网关;用户实际调用是用的 SDK,直接请求直接发送到网关(此时 SDK 已经添加了请求头)。 #### 4.13 backend 中的 invokeInterfaceInfo 怎么根据 url 和 method 调用 client 中不同的方法? 1.封装了一个反射方法,但并没有考虑重载的情况 ![[37ba9e00-e7fb-4840-a40d-22a63907fdce-627bbff4.png]] ![[ae305248-a8e8-462f-944d-1996c3010bb7-14293608.png]] 2.可以直接请求到弄的接口,没经过网关和 client ![[9b395925-6603-4301-ba61-dd281b0e599c-61118111.png]] ![[c92ba3a3-676b-44c7-9aa3-0afdca93b2bc-cfa48c5c.png]] #### 4.14 怎么解决不同 API 接口的发布问题? 做的是个开放平台,所以接入系统的 api 要严格审核检验,让对方遵守你的规则,直接根据接口 id 获取到 url 和请求参数就能调用了。 #### 4.15 大项目可能接收方会用到公共的依赖吗?还是只是对于此项目来说,接收服务的没有使用到公共模块,那事先抽取模块应该遵循什么呢? 在大型项目中,通常会遵循一些最佳实践和规范来设计和组织代码,其中之一就是模块抽取和依赖管理。即使在一些较小的项目中,也建议遵循这些原则,以便更好地维护和扩展代码。 一般来说,模块抽取和公共依赖管理应该遵循以下原则: 1.模块化设计:将功能划分为独立的模块,每个模块都具有明确的功能和职责。这样可以提高代码的可读性和可维护性,方便多人协作开发。 2.单一责任原则:每个模块应该只负责一个主要职责,避免一个模块包含过多的功能或逻辑。这样可以降低模块之间的耦合度,提高代码的可重用性和可测试性。 3.接口抽象:定义清晰的接口或抽象类,规定模块之间的通信协议。这样可以提高模块之间的独立性,使得不同的模块可以灵活地替换和组合。 4.依赖倒置原则:采用依赖倒置原则,将依赖关系从具体实现类向上转移到抽象类或接口。这样可以降低模块之间的耦合度,方便单元测试和代码替换。 5.公共依赖管理:对于公共依赖的库或模块,可以抽取出来作为独立的依赖项,供多个模块使用。这样可以避免重复开发,提高代码的复用性和可维护性。 即使接收服务的模块没有直接使用公共依赖,但这些原则仍然有助于提高代码的可维护性和可扩展性。在某些情况下,接收服务的模块可能会间接地使用到公共依赖,例如通过其他服务或中间件使用了公共依赖。此外,公共依赖的抽取和管理也有助于代码的可读性和可管理性,方便多人协作和维护。 因此,即使在一些较小的项目中,建议遵循模块抽取和公共依赖管理的原则,以便更好地组织和管理代码。 #### 4.16 前端请求 interfaceinfo 显示 5000 系统错误,后端测试调用也 5000,应该从哪开始找问题? 1. 报错日志、debug 2. java 报错 #### 4.17 如果能拦截到了对应的 HTTP 请求,能获取到请求头的所有 kv 参数,再填充到自己的 HTTP 请求头参数中,那么这样跟直接传送 sk 有什么区别吗? 首先秘钥(sk)能不传输就不传输,双方各自存放在服务器本地就不会出现被拦截泄露的风险,而且也不会出现请求头被打到日志中、因为日志泄露导致秘钥泄露的情况。 如果真的像你说的能拦截到签名数据,那确实就是不安全的,就跟你的用户名密码(cookie)泄露了是一样的,可以通过下面 2 种方式进一步提高安全性: 1)使用 https 来加密数据传输,防止请求被中间人劫持和篡改。 2)在签名算法中使用时间戳或随机数,服务器端验证时间戳或随机数的有效性,从而防止重放攻击。 #### 4.18 controller 类里的测试接口是否可用的代码,只能测试自己写的测试接口,那如果我们需要调用的接口没有遵守这个规范怎么办? 所有的接口都是在我们系统里的, 就算开放了接口给外部开发者开发,我们也要人工审核(审核的时候对不符合规范的接口打回或者自行修改)然后将该接口整合进我们的系统,所以接口规范都是统一的。 对于不同参数的接口,可以根据请求的接口的路径地址和接口的请求方法去匹配对应的接口。 #### 4.19 spring boot start、open feign、dubbo 是不是都可以用来封装 SDK?那为什么我们选用了 spring boot start 而不是另外两种? 1.成本问题,starter 明显教学使用方便,不然就有杀鸡用牛刀的感觉,自己做项目你还得判断能否cover 住,假如面试官问 open feign dubbo 底层原理之类的,你是否能 cover,这些都是要考虑的点,不是说技术用的越牛逼越新的越好。 2.SDK 的作用是为了简化开发者调用,尽量精简。 #### 4.20 有没有自动化上传接口的方法?前端同学能不能自己上传接口?用户自己上传接口要怎么实现? 1)无论你通过什么方式写接口、调用谁的接口,都需要把接口注册到API开放平台中,这种注册一般是通过在数据库中保存接口信息实现的,你可以通过读取数据库的接口信息(比如方法名称、接口地址),通过网关的动态路由自动完成对应接口的API调用,也可以通过反射自动根据接口信息生成SDK代码。 如果你是指能不能不写代码调用百度的接口,我劝你打消这个念头,没有这个必要,一般第三方接囗都会给你提供SDK调用的,也要根据业务实际情况选择传哪些参数去调用。 2)你可以仔细思考下前端同学自己上传接口合理么?前端同学需要的是根据后端的接口编写请求代码、获取示例数据从而完成页面的开发,而不是自己写接口、自己传接口。 需要用户上传接口的话,要有一个非常严格的审批机制,确保用户的接口代码是合理的。实际上用户调用任何接口都要通过你的网关,你可以让用户提供一个接口地址,然后你编写或者生成对应的代码来完成接口的转发调用,其他的流程同上一个问题。自己理解一下吧。 #### 4.21 这段代码不理解,是不是 @ConfigurationProperties("yuapi.client") 这个注解不需要了?模拟调用接口是不是通过读取配置文件来获取 ak、sk? ![[d1632153-0351-4ead-a81a-bedfa6cefeec-bd1b7c92.png]] 1.这个注解是从配置文件 yml 中取参数,如果去掉的话,可以自己 new Client 也就是客户端,手动去传入 ak 和 sk,稍微麻烦点。 2.这个的作用是从配置文件中获取 accessKey secretKey 属性值注入给成员变量 accessKey secretKey 赋值,从而创建 bean YuApiClient。 #### 4.22 项目亮点可以说实现了自定义注解吗? 自定义注解的确是一个基础操作,如果有更多内容,可以不写这点哈。 #### 4.23 在网上找了一些接口,该怎么在项目中新增进去?想美化前端界面,有没有鱼友有合适的笔记参考或者基本思路? 新加的话推荐使用反射,将 sdk 里面的方法都反射出来调用。还有个简单的就是使用 if 语句,每次添加就写一个 else,但是不利于维护。 #### 4.25 统计接口调用次数那里,会不会涉及到并发?具体什么时候会出现并发问题? 1.疯狂点击接口,会出现接口为负数。 2.判断剩余次数是否 >0 3.调用接口 4.剩余次数 -1 当有大量请求同时进来,步骤一都是 true,就会超量调用。可以考虑使用 redisson 加用户锁,使每个用户的请求都是逐个执行的。 #### 4.26 面试题:为什么要做这个平台?业内有没有类似的平台,你和它的区别是什么?你是怎么做的,有没有参考其他的平台或者是开源项目? 1. 为什么要做这个平台?其实就是项目的背景和意义,每个项目直播的第一期都会讲。这里你可以补充一点:是为了学习某些技术,然后引导面试官去提问对应的技术知识。 2. 业内有没有没有类似的平台?当然有,专门的API开放平台有搏天API、rapid api等等;此外,基本上大规模的知名产品,都有自己的开放平台;还有像腾讯云之类的云服务商,也提供了大量的 API调用。 3. 你和业内 API开放平台的区别是什么?不要企图回答你的项目比业内项目更成熟,你就说是自己实现的,接入了很多“自己自定义”的接口,就足够了。 4. 你是怎么做的?就回答你是怎么做的。 5. 有没有参考其他的平台或开源项目?如果你自行给项目做了扩展,那么完全可以放心说是参考了网上教程,并且在此基础上改造的。 #### 4.27 为什么要在 interface 项目里引入 sdk 依赖?这个 interface 不是远程被调用的接口吗?为什么还要配置这个呢? 1. 这个 sdk 是封装了请求路径以及一系列的重复操作,它不单单针对你一个人,他到时候可以单独抽取出来供他人使用,更方便用户请求接口,你也可以不使用 sdk 来请求,直接请求地址,这只是鱼总教的一种方法。 2. 想想生成签名是不是由谁来做呢?如果没有 sdk,别人调用你的接口,你叫别人自己写一遍生成签名的流程? #### 4.28 线上数据库、redis、域名注册之类要自己去腾讯云购买吗? 云服务器可以装 mysql 和 redis,域名可以看云服务商有没有做活动,便宜的几块钱一年,上线在云服务商备个案即可。 #### 4.29 对于 API 签名认证,这里面代码没看懂,能讲讲这中间的认证流程吗? ![[5c67f4b2-55d2-4800-9ef9-0fb7b13a35e4-50b136a5.png]] #### 4.30 ak、sk 是不是没有用到?有很多接口后,YuApiClient 如何知道调用了什么方法?如果 YuApiClient 没有读取 backend 中配置的 ak、sk,那 YuApiClient 有什么用? 1.new 和配置文件是两种不同的调用形式,用哪种都可以。 2.可以通过写一个反射方法,根据接口名称调用指定的方法 3.没有读取到 ak,sk 即使转发到 Gateway 也不会调用成功。理论上在 invoke 里也可以直接发送请求到网关,但这个 client 主要是为了简化用户调用你接口时操作,不用自己去发 http 请求,生成各种请求头之类的。 #### 4.31 为什么使用 [http://127.0.0.1:8000](http://127.0.0.1:8000/) 登录后,点击接口查看,页面会跳转到登录页,使用 localhost就没事? sessionid 不一样,所以登录后面请求后端在 session 里拿到的是 null,所以就是未登录,然后让你重新登录。 #### 4.32 有必要在用户调用接口那里防止用户超量调用吗(用户高并发调用)? 1.一分钟超过多少调用,直接拒绝掉,实现也很简单:redis。 你不可能为了 1% 的超量用户调用,把 99% 的正常用户的需求给打挂。那 1% 就算是正常调用,也得进行限制。 2.一个用户一分钟只能调用多少次,可以根据 ip 限流,或者对某个用户的 id 等信息做一个限流吧,具体可以了解一下令牌桶或者漏桶算法应该可以满足你的需求,在网关限流一下。 #### 4.33 docker 部署的 nacos 容器和自己去官网下载的压缩包手动部署有何区别?为什么 2G2核服务器 docker 部署有时候会出现问题? 2G 为啥用不上 docker?2G 单核是最低配置,但是不代表 docker 部署完服务能起来,饿不死和能干活是两个概念。 #### 4.34 后续拓展的话,如果对有高并发对接口进行访问,怎么对接口进行限流呢? 可以看下智能 BI 项目最新一期的直播,提到了限流。 #### 4.35 关于 API 签名这部分知识,想知道不是可以通过用户登录和权限分配,就能够实现校验访问用户是否有调用某个接口的权限了吗?为啥还要使用 API 签名认证? 登录校验访问是做登录校验,API签名认证是做调用校验。 ![[838fe8da-28bb-4d88-98aa-4a85ee6db676-47ae27c7.png]] #### 4.36 部署项目,没有全局请求类,要去哪里找? #### 4.38 MySQL 数据库需要怎么部署? 数据库要么服务器自己用宝塔创建,然后搬运本地数据库的内容,或者买数据库但没必要。 #### 4.39 面试官如果问 api 项目做的过程中遇到的最大的困难是什么,应该怎么回答? 1.可以根据鱼皮整理的项目亮点,去思考下自己以往的项目 2.给系统做的优化基本都可以说下,从接口性能,扩展性等,比如某个接口耗时 6s,你给优化到553ms。 3.伙伴匹配系统,里面有讲并发编程的一下技术知识。 #### 4.40 后端如何动态的调用不同的接口(封装的 sdk 中的不同方法)? 1.可以用 map 2.通过反射,根据携带的请求路径和方法名去调用 3.通过apiSign直接查找数据库,apiSign是唯一的 #### 4.41 有没有鱼友把项目的前后端优化、改进? 1. 可以看看作业榜其他鱼友的完成情况、网站、笔记、优化。 2. 不想写前端或后端代码,可以直接把鱼总的前后端代码拉取下来跑,根据 bug 解决对应问题。 #### 4.42 用户上传接口后,网关怎么自动生成对应路由? 通过路由配置进行统一转发。 #### 4.43 请问项目有多个系统组成算是一个分布式项目那它和微服务的区别在哪里或者需要加些什么才能去讲这是一个微服务项目? 个人理解,微服务项目一般是把整个很大的系统拆分为不同职责的服务,各个服务协作完成整个系统,比如电商系统的订单、用户、支付、搜索等服务;而 API 开放平台的各个模块并不是服务于完整系统的、而是用于对接不同的用户(比如开发者sdk,模拟接口),所以严格来说它不算是微服务项目。不过即使你把他说成是微服务项目,也没有问题,毕竟也用了Dubbo 框架,Gateway 网关技术。 #### 4.44 调用 api 的接口怎么复用? 可以使用反射,根据用户在线调用的接口 url 找到对应的客户端包方法;或者直接把请求甩给网关,通过 url 找到方法名,有了方法名就可以调用了。 #### 4.45 查看接口文档页面中的请求地址是不是应该放网关的地址?让用户去请求网关,网关帮忙转发? 对的,应该放网关的地址。 #### 4.46 项目需要提前配置好 redis 吗? 如果不用分布式 session 就不用配置。api 项目没有用 redis 存储什么数据。 #### 4.47 如果利用网关转发请求,那请求怎么动态转发到目的主机呢? 可以使用一种称为"反向代理"或"负载均衡器"的机制来动态地转发请求到目标主机。以下是这种思路的基本步骤: 1.接收初始请求:当你的API开放平台的客户端发送请求到你的网关(例如,xxx.com/api/user)时,你的网关首先接收到这个请求。 2.解析请求头:你的网关需要解析这个请求,包括请求方法、路径、查询参数、请求头等。 3.查找目标服务器:在接收到请求后,你的网关需要查找或确定目标服务器。这可以通过多种方式实现,例如: -使用内置的服务器列表:如果你的网关知道所有可能的目标服务器,它可以简单地选择一个进行转发。 -使用负载均衡算法:如果你的目标服务器集群更大,你的网关可能需要一个更复杂的策略来选择一个服务器,例如轮询、随机选择、根据服务器负载情况选择等。 -使用服务注册与发现:如果你的目标服务器是动态的或者经常变化的,你可能需要一个服务注册与发现机制,让服务器可以动态地注册自己,而你的网关可以随时发现新的服务器。 4.构造转发请求:一旦你的网关确定了目标服务器,它就需要构造一个新的请求,这个请求的目标是目标服务器的地址。这个请求应该包含从原始请求中获得的所有信息,如HTTP方法、路径、查询参数和请求头等。 5.转发请求:最后,你的网关将新的请求转发到目标服务器,并等待响应。 6.处理响应:当你的网关从目标服务器接收到响应时,它会将这个响应返回给原始的客户端。需要注意的是,返回响应时可能需要处理一些内容,例如去除一些头部信息(例如服务器响应头)等。 在技术实现上,可以使用现有的反向代理服务器或者负载均衡器,例如Nginx、HAProxy等,也可以使用云服务提供商提供的负载均衡服务,例如阿里云的SLB、腾讯云的CLB等。 当然也可以基于OpenResty等框架进行定制开发。 如果你想在请求头中添加一个字段标识真正的目的主机,然后根据这个字段选择真正的目的服务器转发,那么你可以在转发请求时添加一个新的请求头字段(例如X-Real-Host),然后在目标服务器上解析这个字段获取真正的主机地址。但是这种方式需要目标服务器支持这种机制,而且可能会有安全风险。 #### 4.48 怎么扩展限流功能? 1. Gateway 内置了一个请求限流过滤器的,可以参考官方文档,也建议通过官方文档来了解Gateway相关的特性。文档地址: 也可以参考一些博客: 不过我更建议换种通用的方式实现限流,别和 Gateway 绑定。比如在智能 BI 项目中提到了如何运用 Redisson 的 RateLimiter 实现分布式限流,可以先看下该项目的笔记来定位知识点对应的直播位置,当然时间足够的话更推荐学习下 Sentinel。 2)在Gateway 中实现自定义配置局部过滤器,可以参考这篇文章: 3)Gateway 过滤器中,order 越小,优先级越高,建议自己测试一下,具体的执行顺序以测试结果为准。 #### 4.49 为什么不能只用 accessKey 进行签名和验证? 无论你怎么理解,必须要有 “账号” + “密码”,你的想法只不过是把 id 当成账号、accessKey 当成密码罢了,但是注意签名一定是需要密钥的。 #### 4.50 项目可以修改一下拿来做毕设吗?会不会被查重?或者技术含量不够? 可以作为毕设,软件源码不查重,技术够,可以自己进行改造。 #### 4.51 在前端写接口文档地址信息时,里面的接口信息不是已经暴露了。这是否意味着安全性没有得到保证? 两个用法不同,SDK 是给后端开发者用的,开发者无需在意地址只需调用方法就可以拿到结果,给一个 url 感觉可以理解为给前端直接显示调用用的,或者有人想测试的时候直接用这个 url 试试结果吧。 #### 4.52 idea 怎么同时启动多个项目? 1. ALT+8 开启 service 2. 教程有演示: #### 4.53 dubbo + nacos 的实际意义大吗?不是可以直接用父子项目解决即可吗? 1. 微服务拆分:Dubbo 是一种 RPC 框架,它允许你将系统拆分成微服务,每个微服务负责一个具体的业务功能。这样做的好处是,可以实现服务的解耦,提高系统的可维护性和可扩展性。 2. 服务注册与发现:Nacos 是一种服务注册与发现组件,它可以和 Dubbo 配合使用,实现微服务之间的动态服务发现和负载均衡。这样,当服务数量众多时,服务之间的依赖关系可以更加灵活和动态。 3. 服务治理:Nacos 不仅仅提供服务注册和发现的功能,它还提供了更全面的服务治理功能,包括配置管理、动态配置服务、服务监控等,这对于大型分布式系统的稳定运行至关重要。 4. 跨项目调用:虽然在 SpringBoot 中父子项目可以直接调用方法,但在实际的分布式系统中,服务之间的调用往往是跨网络的,这涉及到网络延迟、数据一致性、容错处理等一系列问题,这些都是 Dubbo 和 Nacos 需要解决的问题。 5. 生产环境的考虑:在生产环境中,我们不仅仅要考虑如何实现功能,还要考虑如何保证系统的稳定性、可伸缩性和可维护性。Dubbo 和 Nacos 为这些考虑提供了支持。 #### 4.54 项目用的后端模板是老版本的 or 新版本? 用的是老版本 ![[e4f6fbc4-48c6-46a1-9cdb-2ea244313d4b-9f54a6ce.png]] #### 4.55 项目用 ak/sk 实现签名认证,用用户名和密码充当 ak/sk 不行吗? 1. 假如一个非法攻击请求,那岂不是只要拿到你的用户名和密码就直接为所欲为了,使用 ak、sk 还能保护一下,不让随便一个人就调用接口,api 签名适用于无需保存登录态的场景,只看签名,不关注用户登录态。 2. 可以防止重放 3. ak,sk 可以切换的,账号和密码能随意切换吗,尤其是账号 举例: 假设你有一扇门,这扇门连接着你的房间和外面的世界。你希望确保只有你允许的人可以进入你的房间,而其他人无法进入。为了实现这个目标,你决定设置一把钥匙来锁上这扇门。 现在,我们来比较两种方案: 1. 使用用户名和密码: 你把这扇门锁上,并将钥匙的一份复制留在门外的钥匙盒中。每个人都可以看到这把钥匙,但是只有持有正确用户名和密码的人才能打开这扇门。这种方案中,用户名和密码就像是你的身份证明,只有身份证明正确的人才能使用这把钥匙打开门。 2. 使用 AK/SK(Access Key 和 Secret Key): 你把这扇门锁上,并将钥匙的一份留在你的钥匙包中,只有你知道这个钥匙在哪里。任何人都无法通过外观来获得这把钥匙,只有你知道怎样正确使用这把钥匙。AK/SK 就像是你个人的私密信息,只有持有正确的 AK/SK 的人才能打开门。 在这两种方案中,显然第二种方案更加安全和可靠。虽然第一种方案使用用户名和密码也能达到基本的安全目标,但是这个方法容易受到中间人攻击或者密码泄露的风险。而 AK/SK 方式则能更好地保护你的门不被未经授权的人打开。 --- **项目分区导航**:⬅️ [[18-鱼友真实面经(2) - API 开放项目项目教程 - 编程导航教程|18-鱼友真实面经(2) - API 开放项目项目教程 - 编程导航教程]] | 19-API 开放平台问题答疑 - API 开放项目项目教程 - 编程导航教程 | ➡️ [[01-项目总览|01-项目总览]]